<html>
<script type="text/javascript">
// 一般写法 2017-03-27 7:33PM dinner finished
/*
关于js中 call、apply、bind 的用法可参考这篇博客（http://www.cnblogs.com/xljzlw/p/3775162.html
Requirement:
已知函数 fn 执行需要 3 个参数。请实现函数 partial，调用之后满足如下条件：
1、返回一个函数 result，该函数接受一个参数
2、执行 result(str3) ，返回的结果与 fn(str1, str2, str3) 一致 

*/
var sayIt = function(greeting, name, punctuation) { 
	return greeting + ', ' + name + (punctuation || '!'); 
}; 

console.log(partial(sayIt, 'Hello', 'Ellie')('!!!'));
console.log(partial2(sayIt, 'Hello', 'Ellie')('!!!'));
console.log(partial3(sayIt, 'Hello', 'Ellie')('!!!'));
console.log(partial4(sayIt, 'Hello', 'Ellie')('!!!'));
console.log(partial5(sayIt, 'Hello', 'Ellie')('!!!'));
console.log(partial6(sayIt, 'Hello', 'Ellie')('!!!'));


function partial(fn, str1, str2) {
    function result(str3) {
        return fn(str1, str2, str3); //////////////////////////
    }

    return result;
}

function partial2(fn, str1, str2) {
    function result(str3) {
        return fn.call(this, str1, str2, str3); ////////////////////////
    }

     return result;
}

// apply（这里只是为了对照）
function partial3(fn, str1, str2) {
    function result(str3) {
        return fn.apply(this, [str1, str2, str3]); ////////////////
    }

    return result;
}

// 这个bind会生成一个新函数对象, 它的str1, str2参数都定死了, str3未传入, 一旦传入就会执行
function partial4(fn, str1, str2) {
    return fn.bind(this, str1, str2); // 或 return fn.bind(null, str1, str2);
}


// bind同上, 多了一步, 把str3传入的过程写在另一个函数里面, 而另一个函数也有str1, str2参数
function partial5(fn, str1, str2) {
    function result(str3) {
        return fn.bind(this, str1, str2)(str3);
    }

    return result;
}


// 匿名函数
function partial6(fn, str1, str2) {
    return function(str3) {
        return fn(str1, str2, str3);
    }
}

const partial7 = (fn, str1, str2) => str3 => fn(str1, str2, str3);
console.log(partial7(sayIt, 'Hello', 'Ellie')('!!!'));

</script>
</html>